

#include <cstdint>
#include <string>
#include <iostream>
#include <map>
#include <sstream>

#include <tenacitas.return_code.core/rc.h>

#include "runtest.h"

namespace tenacitas {
/** ==> namespace for the project */
    namespace return_code {
/** ==> application, bussiness, display, interaction, process, storage,
    transmittion */
        namespace core {

            class rc_tester {

            private:
                static bool test1() {
                    std::cerr << "\n+++ rc_tester::test1" << std::endl;
                    return rc<>();
                }

                static rc<> success() {
                    return rc<>();
                }

                static rc<> fail() {
                    rc<> l_rc (200, 32, __FILE__, __LINE__);
                    return l_rc;                    
                }
                
                static bool test2() {
                    std::cerr << "\n+++ rc_tester::test2" << std::endl;
                    rc<> l_rc = success();
                    return l_rc;
                }

                static bool test3() {
                    std::cerr << "\n+++ rc_tester::test3" << std::endl;
                    rc<> l_rc = fail();

                    if (l_rc.get_class_id() != 200) {
                        return false;
                    }

                    if (l_rc.get_constant_id() != 32) {
                        return false;
                    }
                    
                    return !l_rc;
                }
                
                static bool test4() {
                    std::cerr << "\n+++ rc_tester::test4" << std::endl;
                    rc<> l_rc_1 (fail());

                    rc<> l_rc (std::move(l_rc_1));

                    if (l_rc.get_class_id() != 200) {
                        return false;
                    }

                    if (l_rc.get_constant_id() != 32) {
                        return false;
                    }
                    
                    return !l_rc;
                }

                static bool test5() {
                    std::cerr << "\n+++ rc_tester::test5" << std::endl;
                    rc<> l_rc_1 ((fail()));

                    rc<> l_rc(std::move(l_rc_1));

                    if (l_rc.get_class_id() != 200) {
                        return false;
                    }

                    if (l_rc.get_constant_id() != 32) {
                        return false;
                    }
                    
                    return (!l_rc);
                }

                static bool test6() {
                    std::cerr << "\n+++ rc_tester::test6" << std::endl;
                    rc<> l_rc_1 (fail());

                    rc<> l_rc(std::move(l_rc_1));

                    if (l_rc.get_class_id() != 200) {
                        return false;
                    }

                    if (l_rc.get_constant_id() != 32) {
                        return false;
                    }
                    
                    return (!l_rc);
                }

                static bool test7() {
                    std::cerr << "\n+++ rc_tester::test7" << std::endl;
                    rc<> l_rc_1 (fail());

                    rc<> l_rc (std::move(l_rc_1));

                    if (l_rc.get_class_id() != 200) {
                        return false;
                    }

                    if (l_rc.get_constant_id() != 32) {
                        return false;
                    }
                    
                    return (!l_rc);
                }

                static rc<int16_t> m1() {
                    return rc<int16_t>(93);
                }
                
                static bool test8() {
                    std::cerr << "\n+++ rc_tester::test8" << std::endl;
                    rc<int16_t> l_rc = m1();

                    if (!l_rc) {
                        return false;
                    }

                    return (l_rc.get_obj() == 93);
                }

                static bool test9() {
                    std::cerr << "\n+++ rc_tester::test9" << std::endl;
                    rc<int16_t> l_rc;

                    l_rc = m1();
                    
                    if (!l_rc) {
                        return false;
                    }

                    return (l_rc.get_obj() == 93);
                }
                
                static rc<std::string> m2() {
                    return rc<std::string>(98321045,2344,__FILE__,__LINE__);
                }

                static bool test10() {
                    std::cerr << "\n+++ rc_tester::test10" << std::endl;
                    auto l_rc = m2();
                    std::cerr << l_rc << std::endl;
                    
                    return  (l_rc == false);
                }

                static bool test11() {
                    std::cerr << "\n+++ rc_tester::test11" << std::endl;
                    auto l_rc = m2();
                    std::cerr << l_rc << endl;
                    if (l_rc) {
                        return false;
                    }

                    l_rc = rc<std::string>("good!");

                    if (!l_rc) {
                        return false;
                    }

                    std::cerr << "create_rc_tester::test11, l_rc.get_obj() == " <<
                        l_rc.get_obj() << std::endl;
                    
                    return (l_rc.get_obj() == "good!");
                }
                
                static bool test12() {
                    std::cerr << "\n+++ rc_tester::test12" << std::endl;
                    rc<char> l_1('q');

                    std::cerr << l_1.get_obj() << std::endl;

                    return true;
                }


                static bool test13() {
                    std::cerr << "\n+++ rc_tester::test13" << std::endl;
                    rc<char> _r1(123456,103,__FILE__,__LINE__);

                    rc<int16_t> _r2(_r1);
                    

                    std::cerr << "r1 = " <<_r1 << std::endl;
                    std::cerr << "r2 = " <<_r2 << std::endl;

                    return (
                        (_r1.get_class_id() == _r2.get_class_id()) &&
                        (_r1.get_constant_id() == _r2.get_constant_id()) &&
                        (_r1.get_file() == _r2.get_file()) &&
                        (_r1.get_line() == _r2.get_line()) &&
                        (_r1.get_desc() == _r2.get_desc())
                        );
                }

                struct a14 {
                    a14(int16_t p_i = -37)
                        : m_i(p_i) {}
                    
                    a14(a14 && p_a)
                        : m_i (std::move(p_a.m_i)) {}

                    a14 & operator=(a14 && p_a) {
                        m_i = p_a.m_i;
                        return *this;
                    }

                    a14(const a14 &) = delete;

                    a14 & operator=(const a14 & p_a) = delete;

                    int16_t get() {
                        return m_i;
                    }
                    
                private:
                    int16_t m_i;
                };
                
                
                static bool test14() {
                    std::cerr << "\n+++ rc_tester::test14" << std::endl;
                    rc<a14> _r1(a14(18));

                    a14 _a14(_r1.get_obj());

                    return (_a14.get() == 18);
                }

                struct a15 {
                    a15(int16_t p_i = -37)
                        : m_i(new int16_t(p_i)) {}
                    
                    a15(a15 && p_a)
                        : m_i (std::move(p_a.m_i)) {
                        p_a.m_i = nullptr;
                    }

                    a15 & operator=(a15 && p_a) {
                        m_i = p_a.m_i;
                        p_a.m_i = nullptr;                        
                        return *this;
                    }

                    a15(const a15 &) = delete;

                    a15 & operator=(const a15 & p_a) = delete;

                    int16_t get() {
                        return *m_i;
                    }

                    ~a15() {
                        if (m_i != nullptr) {
                            delete m_i;
                            m_i = nullptr;
                        }
                    }
                    
                    
                private:
                    int16_t * m_i;
                };
                
                
                static bool test15() {
                    std::cerr << "\n+++ rc_tester::test15" << std::endl;
                    rc<a15> _r1(a15(18));

                    a15 _a15(_r1.get_obj());

                    return (_a15.get() == 18);
                }

                static bool test16() {
                    std::cerr << "\n+++ rc_tester::test16" << std::endl;

                    int16_t * _j (new int16_t(21));
                        
                    rc<int16_t *> _r1(&_j);

                    int16_t * _i = _r1.get_obj();

                    bool _b = (*_i == 21);

                    delete _i;

                    _i = nullptr;

                    return _b;
                }
                
            public:
                static void run() {
                    runtest(rc_tester::test1());
                    runtest(rc_tester::test2());
                    runtest(rc_tester::test3());
                    runtest(rc_tester::test4());
                    runtest(rc_tester::test6());
                    runtest(rc_tester::test7());
                    runtest(rc_tester::test8());
                    runtest(rc_tester::test9());
                    runtest(rc_tester::test10());
                    // runtest(rc_tester::test11());
                    // runtest(rc_tester::test12());
                    // runtest(rc_tester::test13());
                    // runtest(rc_tester::test14());
                    // runtest(rc_tester::test15());
                    // runtest(rc_tester::test16());
                }
                
            };
        }
    }
}


